﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Windows.Forms;

namespace Clustering_IA_Project
{
    public class rigaDocTerm
    {
        public string page;
        public Dictionary<WordXML, float> riga;
        public rigaDocTerm(string page, Dictionary<WordXML, float> riga)
        {
            this.page = page;
            this.riga = riga;
        }
    }

    class DocTermMatrix
    {
        private List<WordXML> list;
        private List<string> document = new List<string>();  //tutte le pagina visitate
        private List<rigaDocTerm> matrix;
        private  List<WordXML> terms = new List<WordXML>();  //tutti i termini visionati

        /// <summary>
        /// Costruttore
        /// </summary>
        /// <param name="list">lista delle word</param>
        /// <param name="document">lista dei documenti</param>
        public DocTermMatrix(List<WordXML> list)
        {
            this.list = list;
        }

        public List<rigaDocTerm> getMatrix()
        {
            return matrix;
        }

        /// <summary>
        /// Crea o  aggiorna una lista senza duplicati delle pagine visualizzate
        /// </summary>
        /// <param name="l">lista delle word</param>
        /// <returns></returns>
        private void createListDocument(List<WordXML> l)
        {
            List<string> documentWithDuplicates = new List<string>();
            //creo una lista dei documenti visitati
            foreach (WordXML wx in l)
            {
                if( !(document.Contains(wx.webPage)))
                    documentWithDuplicates.Add(wx.webPage);
            }
            //creo una nuova lista dei documenti enza duplicati
            document.AddRange(documentWithDuplicates.Distinct().ToList());
        }

        /// <summary>
        /// Metodo che a partire da una stringa di word, webpage, contesto tutti concatenati
        /// restituisce il valore della matrice DocTerm
        /// </summary>
        /// <param name="key">stringa di ingresso</param>
        /// <param name="key">termine da cercare</param>
        /// <returns>valore della matrice</returns>
        public float getValue(string pg, WordXML word)
        {
            string p = pg;
            WordXML wx = word;
            foreach( rigaDocTerm rdt in matrix )
            {
                if( rdt.page.Equals(p))
                {
                    foreach (KeyValuePair<WordXML, float> pair in rdt.riga)
                    {
                        if(wx.equals(pair.Key))
                            return pair.Value;
                    }
                }
            }
            return 0f;
        }

        /// <summary>
        /// Crea o aggiorna la lista dei termini
        /// </summary>
        /// <param name="l"></param>
        private void createListTerm(List<WordXML> l)
        {          
            List<WordXML> t = new List<WordXML>();
            List<WordXML> l2 = new List<WordXML>();
            //elimino i duplicati dalla lista
            foreach (WordXML wx in l)
            {
                bool b = false;
                foreach (WordXML ww in l2)
                {
                    if (wx.equals(ww))
                    {
                        b = true;
                        break;
                    }
                }
                if (!b)
                    l2.Add(wx);
            }
            //carico la lista in terms eliminando le ripetizioni
            foreach (WordXML wx in l2)
            {
                bool b=false;
                foreach(WordXML ww in terms)
                {
                    MessageBox.Show(ww.word + "-" + wx.word);
                    if (wx.equals(ww))
                    {
                        MessageBox.Show("dentro");
                        b = true;
                        break;
                    }
                }
                if(!b)
                    t.Add(wx);
            }
            //creo una nuova lista dei documenti senza duplicati
            terms.AddRange(t.Distinct().ToList());
        }

        /// <summary>
        /// Crea una lista delle wrod che sono presenti in una data pagina web
        /// </summary>
        /// <param name="l"></param>
        /// <param name="page"></param>
        /// <returns></returns>
        private List<WordXML> createListDocWhereCmpare(List<WordXML> l, string page)
        {
            string p = page;
            List<WordXML> terms = new List<WordXML>();
            foreach (WordXML wx in l)
            {
                if(wx.webPage.Equals(p))
                    terms.Add(wx);
            }
            return terms.Distinct().ToList();
        }

        /// <summary>
        /// Cerca una word in una lista di word
        /// </summary>
        /// <param name="list"></param>
        /// <param name="w"></param>
        /// <returns></returns>
        private bool termIsInPage(List<WordXML> list, WordXML w)
        {
            foreach (WordXML wx in list)
            {
                if(wx.equals(w))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Inizializza i valori della matrice
        /// </summary>
        public void createMatrix()
        {
            matrix = new List<rigaDocTerm>();
            //creo una lista con i nomi delle pagine web
            createListDocument(list);
            //creo una lista con tutti i termini esistemti;
            createListTerm(list);
                        
            foreach (string s in document)
            {
                //creo la lista delle parole che compaiono nella pagina
                List<WordXML> termsPage = createListDocWhereCmpare(list, s);
                Dictionary<WordXML, float> d = new Dictionary<WordXML, float>();
                foreach (WordXML w in terms)
                {   
                    //vedo se la word e' presente nella pagina
                    if(!(termIsInPage(termsPage, w)))
                        d.Add(w, (float)0f);
                    else
                        d.Add(w, (float)((1f / w.numPageWord) * w.fixNumb * w.fixTime));
                }
                rigaDocTerm rg = new rigaDocTerm(s, d);
                matrix.Add(rg);
            }
        }

        public void stampaWx(List<WordXML> l)
        {
            string lista="";
            foreach (WordXML wx in l)
            {
                lista += wx.word;
                lista += "-";
                lista += wx.webPage;
                lista += "-";
                lista += wx.context.Count.ToString();
                lista += "-";
                foreach (string ssss in wx.context)
                {
                    lista += ssss;
                    lista += "--";
                }
                lista += "\n";
            }
            MessageBox.Show(lista);
        }

        public void stampaD(List<string> l)
        {
            string lista = "";
            foreach (string wx in l)
            {
                lista += wx + "\n";
            }
            MessageBox.Show(lista);
        }
        

    
        /*
        public void stampaDC()
        {
            string s = "STAMPA \n\n";
            foreach (rigaDocTerm r in matrix)
            {
                foreach (KeyValuePair<WordXML, float> pair in r.riga)
                {
                    s += "[" + pair.Value + "]  ";
                }
                s += "\n";
            }
            MessageBox.Show(s);
        }*/
    }
}
